//
//  ViewController.m
//  NotificationTest
//
//  Created by wp w on 12-6-22.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "ViewController.h"
#import "Police.h"
#import "Police2.h"
#import "Prisoner.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    
    [self addObserverToNotificationCenter];  
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

#pragma mark - NSObject:observeValueForKeyPath
//观察者要实现的协议（NSObject中方法）：- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
//每个对象都可以添加观察者，只要观察者实现了上述协议
- (IBAction)addObserverTest {
    //新建犯人和警察对象
    Prisoner *prisoner=[[Prisoner alloc] init]; 
    Police *police=[[Police alloc] init];
    NSLog(@"prisoner:0x%x", prisoner);
    NSLog(@"police:0x%x", police);
    
    
    //警察对犯人的名字很感兴趣，他订阅了对犯人的名字变化的事件，这个事件只要发生了，警察就会收到通知。
    //为犯人添加观察者警察，警察关注犯人的name是否发生变化，如果发生变化就立即通知警察，也就是调用Police 中的observeValueForKeyPath方法。 
    
    //addObserver 的调用者是要被监视的对象
    //第一个参数是谁要监视它
    //第二个参数是监视它的哪个属性的变化（使用KVC 机制，也就是前面所说的KVO 基于KVC）
    //第三个参数是监视属性值改变的类型，我们这里监听Old、New，也就是Cocoa会把name 属性改变之前的旧值、改变之后的新值都传递到 Police 的处理通知的方法
    //最后一个参数是自定义参数，会传给观察者。 
    //特别注意：这里有一个陷阱，如果你不小心把forKeyPath的属性名写错了，prisoner里根本就不存在，那么 Cocoa 不会报告任何的错误。所以当你发现你的处理通知的observeValueForKeyPath没有任何反应的时候，首先看一下是不是这个地方写错了。
    [prisoner addObserver: police 
                forKeyPath: @"name" 
                   options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld 
                   context: prisoner]; 
 
    //囚犯改变名字，此时就会通知观察者（警察）
    [prisoner setName: @"豆豆"]; 
    [prisoner setName: @"豆豆2"];
    
    //警察取消订阅犯人名字变化的事件。 
    [prisoner removeObserver: police forKeyPath: @"name"]; 
    [prisoner setName: @"太狼"]; 
    
    [prisoner release]; 
    [police release]; 
}

#pragma mark - NSNotificationCenter
//自己管理NSNotificationCenter
//1.注册观察者函数
//2.将观察者函数添加到通知中心
//3.当事件发生时，调用通知中心，通知观察者

//函数说明
//- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
//observer:观察者
//selector:观察者响应的函数，格式为：- (void)handleNotification:(NSNotification*)notification
//name:要观察事件的一个字符产标示名称。如果为空，则监视发送者发送的所有Notification
//object:发送者。如果发送者为空，则不对发送者做出限制


- (IBAction)NotificationCenterTest {
    //得到通知中心
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
    
    //新建犯人和警察对象
    Prisoner *prisoner=[[Prisoner alloc] init]; 
    Police2 *police=[[Police2 alloc] init];  
    NSLog(@"prisoner:0x%x", prisoner);
    NSLog(@"police:0x%x", police);
    
    //犯人改名，并且通过通知中心通知警察
    [prisoner setName: @"豆豆"]; 

    //向通知中心发送通知，告知通知中心有一个 prisioner_name 的事件发生了，并把自己作为事件源传递给通知中心。 
    //通知中心随后就会查找是谁监听了 prisioner_name 事件呢？找到之后就调用观察者指定的处理方法，也就是Police中的handleNotification 方法被调用。 
    //+ (id)notificationWithName:(NSString *)aName object:(id)anObject;
    //+ (id)notificationWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
    [nc postNotificationName: @"prisioner_name" object:prisoner];   
    
    //犯人改名，但是没有显示通过通知中心通知警察
    [prisoner setName: @"豆豆2"]; 
    
    //从通知中心移除观察者 
    [nc removeObserver: police]; 
    [prisoner setName: @"太狼"]; 
    
    [prisoner release]; 
    [police release]; 
}

//系统管理NSNotificationCenter
- (void)addObserverToNotificationCenter
{
//    UIApplication *app = [UIApplication sharedApplication];
//    NSLog(@"app:0x%x", app);
//    NSLog(@"self:0x%x", self);
//    [[NSNotificationCenter defaultCenter] addObserver:self
//                                             selector:@selector(myapplicationDidEnterBackground:)
//                                                 name:UIApplicationDidEnterBackgroundNotification 
//                                               object:app];
}

- (void)myapplicationDidEnterBackground:(NSNotification*)notification
{
    NSLog(@"view myapplicationDidEnterBackground:");
    NSString *name = [notification name];
    NSLog(@"name:%@", name);
    
    id *object=[notification object];//获得通知中心传递过来的事件源对象 
    NSLog(@"object:0x%x", object);  
    
    //+ (id)notificationWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
    NSDictionary* userInfo = [notification userInfo];
    NSLog(@"userInfo:%@", userInfo);
}

@end
